﻿using System;
using System.Data;
using System.Data.Objects;
using System.Linq;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace ControlePonto.Extensions
{
    // Base repository class for entity with simple key
    public class RepositoryBase<TEntity, TKey> where TEntity : class
    {
        private readonly string _entitySetName;
        private readonly string _keyName;

        protected ObjectContext Context { get; private set; }
        protected ObjectSet<TEntity> ObjectSet { get; private set; }

        public RepositoryBase(ObjectContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            Context = context;
            ObjectSet = context.CreateObjectSet<TEntity>();

            // Get entity set for current entity type
            var entitySet = ObjectSet.EntitySet;
            // Build full name of entity set for current entity type
            //_entitySetName = context.DefaultContainerName + "." + entitySet.Name;
            _entitySetName = context.GetEntitySetName<TEntity>();
            // Get name of the entity's key property
            _keyName = entitySet.ElementType.KeyMembers.Single().Name;
        }

        
        public virtual TEntity GetByKey(TKey key)
        {
            // Build entity key
            var entityKey = new EntityKey(_entitySetName, _keyName, key);
            // Query first current state manager and if entity is not found query database!!!
            return (TEntity)Context.GetObjectByKey(entityKey);
        }
        
        public virtual IEnumerable<TEntity> Paginate<TOrderType>(string keyFieldName, int take, int skip)
        {
            var param = Expression.Parameter(typeof(TOrderType), typeof(TOrderType).Name);
            var expression = System.Linq.Expressions.Expression.Lambda<Func<TEntity, TKey>>(Expression.Property(param, keyFieldName), param);
       // Now I can get desire entityset from context using reflection.
            return this.ObjectSet.OrderBy(obj => keyFieldName).ToList().Skip(skip).Take(take);
        }
        public virtual IEnumerable<TEntity> ListAll()
        {
            return this.ObjectSet.ToList();
        }
        public virtual TEntity Insert(TEntity entity)
        {
            Context.AddObject(_entitySetName, entity);
            Context.SaveChanges();
            return entity;
        }
        public virtual TEntity Delete(TEntity entity)
        {
            Context.DeleteObject(entity);
            Context.SaveChanges();
            return entity;
        }

        // Rest of repository implementation
    }
}